{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.1 函数基础\n",
    "\n",
    "- 定义： 函数就是为了实现某一功能的代码段，写好以后可以重复利用\n",
    "- 函数定义\n",
    "    + def 是函数的生命\n",
    "    + 函数名称\n",
    "    + 函数参数\n",
    "    + 函数主题\n",
    "    + 函数返回 （return 或 yield)\n",
    "\n",
    "def 是可执行语句，这意味着函数直到被调用前，都是不存在的。当程序调用函数时，def 语句才会创建一个新的函数对象，并赋予其名字。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "接收到的消息是：hello\n"
     ]
    }
   ],
   "source": [
    "def my_func(message):\n",
    "    print('接收到的消息是：{}'.format(message))\n",
    "\n",
    "my_func('hello')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.2 函数嵌套\n",
    "\n",
    "- 函数嵌套，是指在函数内部定义另一个函数\n",
    "- 函数嵌套，可以提高代码的复用性\n",
    "- 函数嵌套，可以提高代码的层次性\n",
    "- 函数嵌套，可以提高代码的复杂性\n",
    "\n",
    "\n",
    "```` python \n",
    "\n",
    "def outer_func():\n",
    "    print('outer function')\n",
    "    def inner_func():\n",
    "        print('inner function')\n",
    "    inner_func()\n",
    "outer_func()\n",
    "\n",
    "def connect_DB():\n",
    "    def get_DB_configuration():\n",
    "        ...\n",
    "        return host, username, password\n",
    "    conn = connector.connect(get_DB_configuration())\n",
    "    return conn\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.3 函数变量作用域\n",
    "\n",
    "- 局部变量：在函数的内部定义，只有在函数的内部有效，一旦函数执行完毕，局部变了就被回收\n",
    "- 全局变量：全局变量定义在整个文件层次\n",
    "    + 函数内部要使用全局变量，必须用Global 声明\n",
    "    + 函数内部局部变量和全局变量同名，局部变量覆盖全局变量\n",
    "    + 函数内部不能修改全局变量，如要修改必须 nonlocal声明"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "MIN_VALUE = 1\n",
    "MAX_VALUE = 10\n",
    "def validation_check(value):\n",
    "    if value < MIN_VALUE or value > MAX_VALUE:\n",
    "        raise Exception('validation check fails')\n",
    "\n",
    "validation_check(8)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "MIN_VALUE = 1\n",
    "MAX_VALUE = 10\n",
    "def validation_check(value):\n",
    "    global MIN_VALUE\n",
    "    MIN_VALUE += 1\n",
    "\n",
    "validation_check(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inner: nonlocal\n",
      "outer: nonlocal\n"
     ]
    }
   ],
   "source": [
    "def outer():\n",
    "    x = \"local\"\n",
    "    def inner():\n",
    "        nonlocal x # nonlocal关键字表示这里的x就是外部函数outer定义的变量x\n",
    "        x = 'nonlocal'\n",
    "        print(\"inner:\", x)\n",
    "    inner()\n",
    "    print(\"outer:\", x)\n",
    "outer()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.4 闭包 closure\n",
    "\n",
    "闭包其实和刚刚讲的嵌套函数类似，不同的是，这里外部函数返回的是一个函数，而不是一个具体的值。返回的函数通常赋于一个变量，这个变量可以在后面被继续执行调用。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<function nth_power.<locals>.exponent_of at 0x000001A87B3AD3A0>\n",
      "<function nth_power.<locals>.exponent_of at 0x000001A87B3AD080>\n",
      "--------------------------------------------------\n",
      "4\n",
      "32\n"
     ]
    }
   ],
   "source": [
    "def nth_power(exponent):\n",
    "    def exponent_of(base):\n",
    "        return base ** exponent\n",
    "    return exponent_of # 返回值是 exponent_of 函数\n",
    "\n",
    "square = nth_power(2) # 计算一个数的平方\n",
    "cube = nth_power(5) # 计算一个数的立方\n",
    "print(square)\n",
    "print(cube)\n",
    "print('-'*50)\n",
    "print(square(2)) # 计算 2 的平方\n",
    "print(cube(2)) # 计算 2 的立方\n",
    "\n",
    "# 这里外部函数 nth_power() 返回值，是函数 exponent_of()，而不是一个具体的数值。需要注意的是，\n",
    "# 在执行完square = nth_power(2)和cube = nth_power(3)后，\n",
    "# 外部函数 nth_power() 的参数 exponent，仍然会被内部函数 exponent_of() 记住。这样，之后我们调用 square(2) 或者 cube(2) 时，\n",
    "# 程序就能顺利地输出结果，而不会报错说参数 exponent 没有定义了。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.5 总结\n",
    "\n",
    "- Python 中函数的参数可以接受任意的数据类型，使用起来需要注意，必要时请在函数开头加入数据类型的检查；\n",
    "- 和其他语言不同，Python 中函数的参数可以设定默认值；\n",
    "- 嵌套函数的使用，能保证数据的隐私性，提高程序运行效率；\n",
    "- 合理地使用闭包，则可以简化程序的复杂度，提高可读性。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
